﻿using UnityEngine;
using UnityEditor;
using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;

/// <summary>
/// 场景截图工具，截取的图片用于区域地图显示
/// </summary>
public class ScenePhotoTool : EditorWindow
{
    // 默认定义几种图片尺寸
    private enum EPhotoSizeType
    {
        _512X512,
        _256X256,
        _192X192,
        _128X128,
        _96X96,
        _64X64,
        _48X48
    }

    private Vector2[] PhotoSizeList =
    {
        new Vector2(512, 512),
        new Vector2(256, 256),
        new Vector2(192, 192),
        new Vector2(128, 128),
        new Vector2(96, 96),
        new Vector2(64, 64),
        new Vector2(48, 48)
    };

    private static Vector2 m_WinMinSize = new Vector2(800, 800);

    //private static Rect m_WinPosition = new Rect(100.0f, 100.0f, 315.0f, 400.0f);
    private static string DEFAULT_PHOTO_SAVE_PATH = Application.dataPath + "/../../../Public/Resource/Public/Scenes";

    private static string MAP_RULER_PATH = "Assets/GameMain/Scripts/Editor/ScenePhoto/mapRuler/mapRuler.FBX";
    private static string PHOTO_CAMERA_PATH = "Assets/GameMain/Scripts/Editor/ScenePhoto/PhotoCamera.prefab";
    public string DebugInfo;

    private Rect SceneRect;
    private EPhotoSizeType PhotoSizeType;
    private Vector2 PhotoSize;
    private Texture2D Photo;
    private string PhotoSavePath;
    private bool IsHDR = true;

    private GameObject MapRulerObj;
    private GameObject PhotoCameraObj;
    private Camera PhotoCamera;
    private bool IsAdvancedConfig = false;

    [MenuItem("Project-S/Scene Planform")]
    private static void Init()
    {
        ScenePhotoTool window = EditorWindow.GetWindow<ScenePhotoTool>("场景拍照工具", true, typeof(EditorWindow));
        window.minSize = m_WinMinSize;
        window.wantsMouseMove = true;
        window.Show();
        window.Initialize();
    }

    private void Initialize()
    {
        SceneRect = new Rect(0, 0, 256, 256);
        PhotoSizeType = EPhotoSizeType._256X256;
        PhotoSize = Vector2.zero;
        PhotoSavePath = DEFAULT_PHOTO_SAVE_PATH + "/Scene.png";
        PhotoSavePath = PhotoSavePath.Replace("\\", "/");

        LoadCamera();
        LoadMapRuler();
    }

    private void ResetData()
    {
        while (true)
        {
            GameObject photoCamera = GameObject.Find("_PhotoCamera");
            if (photoCamera == null)
                break;
            GameObject.DestroyImmediate(photoCamera);
        }
        while (true)
        {
            GameObject mapRulerObj = GameObject.Find("_MapRuler");
            if (mapRulerObj == null)
                break;
            GameObject.DestroyImmediate(mapRulerObj);
        }
        Photo = null;
        PhotoCameraObj = null;
        PhotoCamera = null;
        MapRulerObj = null;
    }

    private void LoadCamera()
    {
        while (true)
        {
            GameObject photoCamera = GameObject.Find("_PhotoCamera");
            if (photoCamera == null)
                break;
            GameObject.DestroyImmediate(photoCamera);
        }
        GameObject photoCameraAsset = AssetDatabase.LoadAssetAtPath(PHOTO_CAMERA_PATH, typeof(GameObject)) as GameObject;
        if (photoCameraAsset != null)
        {
            PhotoCameraObj = GameObject.Instantiate(photoCameraAsset) as GameObject;
            PhotoCameraObj.name = "_PhotoCamera";
            PhotoCamera = PhotoCameraObj.GetComponent<Camera>();
        }
    }

    private void LoadMapRuler()
    {
        while (true)
        {
            GameObject mapRulerObj = GameObject.Find("_MapRuler");
            if (mapRulerObj == null)
                break;
            GameObject.DestroyImmediate(mapRulerObj);
        }
        GameObject MapRulerAsset = AssetDatabase.LoadAssetAtPath(MAP_RULER_PATH, typeof(GameObject)) as GameObject;
        if (MapRulerAsset != null)
        {
            MapRulerObj = GameObject.Instantiate(MapRulerAsset) as GameObject;
            MapRulerObj.name = "_MapRuler";
        }
    }

    private void OnDestroy()
    {
        ResetData();
    }

    private void OnGUI()
    {
        EditorGUILayout.Space();
        SceneRect = EditorGUILayout.RectField("场景矩形", SceneRect);
        EPhotoSizeType oldSizeType = PhotoSizeType;
        PhotoSizeType = (EPhotoSizeType)EditorGUILayout.EnumPopup("原图尺寸", PhotoSizeType, GUILayout.Width(300));
        if (oldSizeType != PhotoSizeType)
            Photo = null;

        EditorGUILayout.BeginHorizontal();
        PhotoSavePath = EditorGUILayout.TextField("原图保存位置", PhotoSavePath);
        if (GUILayout.Button("...", GUILayout.MaxWidth(50)))
        {
            PhotoSavePath = EditorUtility.SaveFilePanel(
              "选择原图的存储位置",
              DEFAULT_PHOTO_SAVE_PATH,
              "Scene",
              "png");
        }
        EditorGUILayout.EndHorizontal();

        IsAdvancedConfig = EditorGUILayout.Foldout(IsAdvancedConfig, "高级");
        if (IsAdvancedConfig)
        {
            IsHDR = EditorGUILayout.Toggle("使用HDR", IsHDR);
            PhotoSize = EditorGUILayout.Vector2Field("自定义原图尺寸", PhotoSize);
        }

        EditorGUILayout.Space();
        GUILayout.BeginHorizontal();
        if (GUILayout.Button("拍照预览"))
        {
            TakePhoto();
        }
        if (GUILayout.Button("原图保存"))
        {
            SavePhoto();
        }
        GUILayout.EndHorizontal();
        EditorGUILayout.Space();

        GUILayout.BeginHorizontal("HelpBox");
        GUILayout.Label("预览视图");
        GUILayout.EndHorizontal();
        EditorGUILayout.Space();

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.BeginVertical();
        GUILayout.Label("[游戏中显示]512X512");
        float textureFildSize = 512;
        EditorGUILayout.ObjectField(
          Photo,
          typeof(Texture2D),
          false,
          GUILayout.MaxWidth(textureFildSize),
          GUILayout.MaxHeight(textureFildSize),
          GUILayout.MinWidth(textureFildSize),
          GUILayout.MinHeight(textureFildSize)
          );
        EditorGUILayout.EndVertical();

        EditorGUILayout.BeginVertical();
        Vector2 texSize = GetPhotoSize();
        GUILayout.Label("[原图]" + texSize.x + "X" + texSize.y);
        EditorGUILayout.ObjectField(
          Photo,
          typeof(Texture2D),
          false,
          GUILayout.MaxWidth(texSize.x),
          GUILayout.MaxHeight(texSize.y),
          GUILayout.MinWidth(texSize.x),
          GUILayout.MinHeight(texSize.y)
          );
        EditorGUILayout.EndVertical();
        EditorGUILayout.EndHorizontal();
        EditorGUILayout.Space();

        this.Repaint();
    }

    private void TakePhoto()
    {
        List<GameObject> airWallMeshes = new List<GameObject>();
        try
        {
            //GameObject airWallContainer = GameObject.FindGameObjectWithTag("StaticAirWall");
            GameObject airWallContainer = GameObject.Find("StaticAirWall");
            if (null != airWallContainer)
            {
                int count = airWallContainer.transform.childCount;
                for (int airIndex = 0; airIndex < count; ++airIndex)
                {
                    Transform airWall = airWallContainer.transform.GetChild(airIndex);
                    if (null != airWall)
                    {
                        GameObject child = GameObject.CreatePrimitive(PrimitiveType.Cube);
                        if (null != child)
                        {
                            child.transform.parent = airWall;
                            child.transform.localPosition = Vector3.zero;
                            child.transform.localRotation = Quaternion.identity;
                            child.transform.localScale = Vector3.one;
                            child.SetActive(true);
                            child.GetComponent<Renderer>().sharedMaterial.shader = Shader.Find("Self-Illumin/Specular");
                            child.GetComponent<Renderer>().sharedMaterial.color = Color.yellow;
                            airWallMeshes.Add(child);
                        }
                    }
                }
            }
            Debug.Log("AirWall Count:" + airWallMeshes.Count);

            if (PhotoCamera == null)
            {
                EditorUtility.DisplayDialog(
                  "Error",
                  "Photo Camera Miss! Are you miss PhotoCamera.prefab?",
                  "OK");
                return;
            }
            Vector2 tSceneSize = SceneRect.size;//SceneBottomRight - SceneTopLeft;
            Vector2 tSceneCenter = SceneRect.center;//(SceneTopLeft + SceneBottomRight) / 2;

            PhotoCamera.orthographic = true;
            PhotoCamera.aspect = 1.0f;
            PhotoCamera.allowHDR = IsHDR;
            PhotoCamera.orthographicSize = Mathf.Max(tSceneSize.x, tSceneSize.y) / 2;
            //PhotoCamera.rect = new Rect(0, 0, tSceneSize.x, tSceneSize.z);
            PhotoCamera.transform.position = new Vector3(tSceneCenter.x, 1000.0f, tSceneCenter.y);
            PhotoCamera.transform.LookAt(new Vector3(tSceneCenter.x, 0, tSceneCenter.y));

            //将场景中的MapRuler隐藏，否则相机会拍到
            bool changedMapRuler = false;
            if (MapRulerObj != null && MapRulerObj.activeSelf)
            {
                changedMapRuler = true;
                MapRulerObj.SetActive(false);
            }

            RenderTexture currentActiveRT = RenderTexture.active;
            Vector2 texSize = GetPhotoSize();
            RenderTexture tCameraRT = new RenderTexture((int)texSize.x, (int)texSize.y, 24);
            PhotoCamera.targetTexture = tCameraRT;
            RenderTexture.active = tCameraRT;
            PhotoCamera.Render();

            Photo = new Texture2D((int)texSize.x, (int)texSize.y, TextureFormat.RGB24, false);
            Photo.ReadPixels(new Rect(0, 0, (int)texSize.x, (int)texSize.y), 0, 0);
            Photo.Apply();

            RenderTexture.active = null;
            PhotoCamera.targetTexture = null;
            RenderTexture.active = currentActiveRT;

            //还原MapRuler之前的显示
            if (changedMapRuler)
            {
                MapRulerObj.SetActive(true);
            }
        }
        catch (Exception ex)
        {
            UnityEngine.Debug.Log("ScenePhoto.TackPhoto failed.ex:" + ex.Message);
        }
        finally
        {
            foreach (GameObject child in airWallMeshes)
            {
                child.transform.parent = null;
                child.SetActive(false);
                GameObject.DestroyImmediate(child);
            }
        }
    }

    private void SavePhoto()
    {
        if (Photo == null)
        {
            EditorUtility.DisplayDialog(
                "提示",
                "请先拍照预览后，再点击照片保存！",
                "OK");
            return;
        }

        string dir = Path.GetDirectoryName(GetPhotoName());
        if (!Directory.Exists(dir))
            Directory.CreateDirectory(dir);

        byte[] bytes;
        bytes = Photo.EncodeToPNG();
        System.IO.File.WriteAllBytes(GetPhotoName(), bytes);

        EditorUtility.DisplayDialog(
        "提示",
        "照片保存完成！",
        "OK");
    }

    private string GetPhotoName()
    {
        return PhotoSavePath;
        /*
        string tPhotoTimeFormat = "yyyyMMddHHmmss";
        return string.Format("{0}/{1}_{2}.png",
          PhotoSavePath,
          "Photo",
          DateTime.Now.ToString(tPhotoTimeFormat));
        */
    }

    private Vector2 GetPhotoSize()
    {
        if (PhotoSize.x < 1 || PhotoSize.y < 1)
        {
            return PhotoSizeList[(int)PhotoSizeType];
        }
        return PhotoSize;
    }
}
